package com.unlcn.ils.sales.backend.service;

import cn.huiyunche.commons.exception.BusinessException;
import com.alibaba.fastjson.JSONObject;
import com.unlcn.ils.sales.backend.util.DateUtils;
import com.unlcn.ils.sales.backend.util.JavaSmsApi;
import com.unlcn.ils.sales.backend.util.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 发送短信工具类
 */
@Service
public class SendMessageService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SendMessageService.class);

    @Autowired
    private UserService userService = null;

    public String sendCaptcha(@RequestParam("phone") String phone) {
        LOGGER.info("SendMessageService.sendCaptcha params : {}, {}, {}.", phone);
        if (StringUtils.isBlank(phone)) {
            LOGGER.info("sendAuthCode{}", phone);
            throw new BusinessException("手机号不能为空!");
        }

        //查询是否已经发送验证码
        if (this.ifCaptchaAlreadyExistsInRedis(phone)) {
            LOGGER.error("captcha is already exists");
            throw new IllegalArgumentException("验证码已发送，请注意查收或稍后再试！");
        }

        // 生成验证码
        String code = RandomUtils.bitInteger(6);
        try {
            String tpl_value = URLEncoder.encode("#code#", JavaSmsApi.getENCODING()) + "=" + URLEncoder.encode(code, JavaSmsApi.getENCODING());
            String flag = JavaSmsApi.tplSendSms(JavaSmsApi.getAPIKEY(), JavaSmsApi.TPL_ID, tpl_value, phone);
            LOGGER.info("SendMessageService.sendCaptcha sendSms return : {}", flag);
            Map<String, String> map = jsontoHashMap(flag);
            /*
			 * cod e = 0: 正确返回。可以从api返回的对应字段中取数据。 code > 0:
			 * 调用API时发生错误，需要开发者进行相应的处理。 -50 < code <= -1: 权限验证失败，需要开发者进行相应的处理。
			 * code <= -50: 系统内部错误，请联系技术支持，调查问题原因并获得解决方案。
			 */
            String resCode = map.get("code");
            if ("0".equals(resCode)) {
                // 存储验证码到redis 失效时间为120秒
                return (this.getUserService().setAuthCode(phone, code, 120));
            } else if ("33".equals(resCode)) {
                return "验证码已成功发送";
            } else {
                throw new BusinessException(map.get("detail"));
            }
        } catch (Exception e) {
            LOGGER.error("SendMessageService.sendCaptcha error : {}", e);
            throw new BusinessException("发送失败!");
        }
    }

    public boolean ifCaptchaAlreadyExistsInRedis(String phone) {
        LOGGER.info("ifCaptchaAlreadyExistsInRedis param : {}, {}", phone);
        return userService.alreadyExists(phone);
    }

    /**
     * 提现发送通知短信
     *
     * @param phone
     * @param card
     * @param amount
     */
    public void sendCashMsg(String phone, String card, String amount) {
        LOGGER.info("SendMessageService.sendCashMsg params : {}, {}.", card, amount);
        try {
            String tpl_value = URLEncoder.encode("#code#", JavaSmsApi.getENCODING()) + "=" + URLEncoder.encode(card, JavaSmsApi.getENCODING());
            tpl_value += "&" + URLEncoder.encode("#date#", JavaSmsApi.getENCODING()) + "=" + URLEncoder.encode(DateUtils.getCurrentZeroDate(DateUtils.FORMAT_DATE_NO_YEAR), JavaSmsApi.getENCODING());
            tpl_value += "&" + URLEncoder.encode("#count#", JavaSmsApi.getENCODING()) + "=" + URLEncoder.encode(amount, JavaSmsApi.getENCODING());
            String flag = JavaSmsApi.tplSendSms(JavaSmsApi.getAPIKEY(), JavaSmsApi.CASH_TPL_ID, tpl_value, phone);
            LOGGER.info("SendMessageService.sendCaptcha sendSms return : {}", flag);
            Map<String, String> map = jsontoHashMap(flag);
			/*
			 * code = 0: 正确返回。可以从api返回的对应字段中取数据。 code > 0:
			 * 调用API时发生错误，需要开发者进行相应的处理。 -50 < code <= -1: 权限验证失败，需要开发者进行相应的处理。
			 * code <= -50: 系统内部错误，请联系技术支持，调查问题原因并获得解决方案。
			 */
            String resCode = map.get("code");
            if ("0".equals(resCode)) {
            } else {
                throw new BusinessException(map.get("detail"));
            }
        } catch (Exception e) {
            LOGGER.error("SendMessageService.sendCaptcha error : {}", e);
            throw new BusinessException("发送失败!");
        }
    }



    /**
     * Send by tpl id.
     *
     * @param tplId the tpl id
     * @param phone the phone
     */
    @Async
    public void sendByTplId(Long tplId, String phone) {
        try {
            this.sendMessage(tplId, "", phone);
        } catch (Exception e) {
            LOGGER.error("sendDispatchDriverErrorMessage 司机派单异常 error : {}", e);
            // throw new BusinessException("司机派单异常");
        }
    }

    // 易宝系统回调成功 短信通知
    public void sendYeepayNotifySuccessMessage(String code, String phone) {
        try {
            String tplValue = URLEncoder.encode("#code#", JavaSmsApi.getENCODING()) + "=" + URLEncoder.encode(code, JavaSmsApi.getENCODING())
                    + URLEncoder.encode("#date#", JavaSmsApi.getENCODING()) + "=" + URLEncoder.encode(DateUtils.getCurrentZeroDate("MM月dd日"), JavaSmsApi.getENCODING());
            long tplId = JavaSmsApi.YEEPAY_NOTIFY_SUCCESS_TPL_ID;
            this.sendMessage(tplId, tplValue, phone);
        } catch (Exception e) {
            LOGGER.error("sendYeepayNotifySuccessMessage 易宝系统回调成功 短信异常 error : {}", e);
        }
    }

    // 易宝系统回调失败 短信通知
    public void sendYeepayNotifyErrorMessage(String code, String phone, String message) {
        try {
            String tplValue = URLEncoder.encode("#code#", JavaSmsApi.getENCODING()) + "=" + URLEncoder.encode(code, JavaSmsApi.getENCODING())
                    + URLEncoder.encode("#message#", JavaSmsApi.getENCODING()) + "=" + URLEncoder.encode(message, JavaSmsApi.getENCODING())
                    + URLEncoder.encode("#date#", JavaSmsApi.getENCODING()) + "=" + URLEncoder.encode(DateUtils.getCurrentZeroDate("MM月dd日"), JavaSmsApi.getENCODING());
            long tplId = JavaSmsApi.YEEPAY_NOTIFY_ERROR_TPL_ID;
            this.sendMessage(tplId, tplValue, phone);
        } catch (Exception e) {
            LOGGER.error("sendYeepayNotifyErrorMessage 易宝系统回调失败 短信异常 error : {}", e);
        }
    }

    public void sendMessage(Long tplId, String tplValue, String phone) {
        LOGGER.info("send order message params telId:{}, tplValue:{}, phone:{}.", tplId, tplValue, phone);
        try {
            String flag = JavaSmsApi.tplSendSms(JavaSmsApi.getAPIKEY(), tplId, tplValue, phone);
            LOGGER.info("send order message params telId:{}, tplValue:{}, phone:{}, return flag:{}.", tplId, tplValue, phone, flag);
            Map<String, String> map = jsontoHashMap(flag);
			/*
			 * code = 0: 正确返回。可以从api返回的对应字段中取数据。 code > 0:
			 * 调用API时发生错误，需要开发者进行相应的处理。 -50 < code <= -1: 权限验证失败，需要开发者进行相应的处理。
			 * code <= -50: 系统内部错误，请联系技术支持，调查问题原因并获得解决方案。
			 */
            String resCode = map.get("code");
            if ("0".equals(resCode)) {
            } else {
                LOGGER.error("sendMessage: {}", map.get("detail"));
                // throw new BusinessException(map.get("detail"));
            }
        } catch (Exception e) {
            LOGGER.error("send order message error 发送业务短信异常 : {}.", e);
            // throw new BusinessException("发送业务短信异常");
        }
    }

    /**
     * json转map
     *
     * @param json
     * @return
     */
    @SuppressWarnings("rawtypes")
    private Map<String, String> jsontoHashMap(String json) {
        LOGGER.info("LoginController.jsontoHashMap param : {}", json);
        Map<String, String> map = new HashMap<>();
        // 将json字符串转换成jsonObject
        JSONObject jsonObject = JSONObject.parseObject(json);
        Iterator it = jsonObject.keySet().iterator();
        // 遍历jsonObject数据，添加到Map对象
        while (it.hasNext()) {
            String key = String.valueOf(it.next());
            String value = String.valueOf(jsonObject.get(key));
            map.put(key, value);
        }
        return map;
    }

    private UserService getUserService() {
        return this.userService;
    }

}